import requests
import hashlib
import re
import json
import random
import pytesseract
import time
import base64
from PIL import Image

# https://sourceforge.net/projects/tesseract-ocr-alt/files/


def to_md5(s):
    '''MD5加密'''
    return hashlib.md5(s.encode('utf-8')).hexdigest()


def to_re(s):
    '''正则表达式'''
    return bool(re.match("^[a-zA-Z0-9]{4}$", s))


def get_random_code(l=6):
    '''返回随机数'''
    return random.randint(100000, 999999) if l == 6 else random.randint(1000, 9999)


def get_verify_code():
    '''解析验证码'''
    image = Image.open('code.jpg')
    vcode = pytesseract.image_to_string(image, lang='eng')
    ncode = vcode.strip().replace(' ', '')
    rcode = to_re(ncode)
    print("验证码1:", ncode, rcode)
    return ncode if rcode else False


def get_token_code(data):
    '''解析token'''
    if not data.get("status") == 1:
        return False
    token = data['data']['token']
    # print("Token:", token)
    return token


def do_quest(i):
    '''解析题目列表'''
    print("题目ID:", i["title"])
    return {"id": i["ueId"], "topicType": i["topicType"], "title": i["title"], "a": i["a"], "b": i["b"], "c": i["c"], "d": i["d"], "rightKey": i["rightKey"],
            "rightRate": i["rightRate"], "analyze": i["analyze"]}


def get_quest_listy(data, idx):
    '''解析题目列表'''
    if not data.get("status") == 1:
        return False
    quest = {i["ueId"]: do_quest(i) for i in data['data']} if idx > 700000 else {
        i["ueId"]: do_quest(i) for i in data['data']['simExamExerciseListPage']}
    return quest


def get_sign(kwargs):
    '''生成签名'''
    appkey = {"VUE_APP_KEY": "a46bf56acb7be4cd"}
    l = list(kwargs.keys())
    l.sort()
    z = [f'{k}={kwargs[k]}' for k in l]
    z = '&'.join(z)
    return to_md5(z+appkey['VUE_APP_KEY'])


class MyClass(requests.Session):
    def __init__(self):
        super().__init__()
        self.host = 'http://mtjy.huibo.com'
        self.headers.update({
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3',
            'Authorization': 'Beego aHVhaGFuOmJlZWdvMjAxNQ=='
        })
        self.rcode = 0
        self.token = ""
        self.umcid = 26736268
        self.idx = {"yuwen": [707000, 707011, 707016, 707024,
                              707030, 707034, 707038, 707041, 707043, 707047, 24963, 24964, 25828, 31583, 21646, 21642, 16193, 7809, 5208]}

        # u = 'http://mtjy.huibo.com/course/simexam/24964?umcid=26736268'   # 模拟
        # u = 'http://mtjy.huibo.com/course/practice/707011?umcid=26736268' # 练习

    def has_token(self):
        """获取token"""
        url = '/BeegoEduApi/api/pc/homePage/findDataByrealmName'
        params = {
            "realmName": "mtjy.huibo.com",
            "agencyId": "",
            "isApi": ""
        }
        res = self.do_get(url, params=params)
        if res.status_code == 200:
            token = get_token_code(res.json())
            return token
        else:
            return False

    def has_code(self):
        """请求验证码"""
        self.rcode = get_random_code()
        url = '/BeegoEduApi/rest/getCode'
        params = {'randdomCode': self.rcode}
        res = self.do_get(url, params=params)
        if res.status_code == 200:
            with open('code.jpg', 'wb') as f:
                f.write(res.content)
            return get_verify_code()
        else:
            return False

    def has_login(self, code):
        """登录"""
        url = '/BeegoEduApi/api/pc/login'
        d = {
            'type': 1,
            'username': 'CJ24Q211',
            'password': 'a95aa44766a8e63c0db905f04d549ab7',
            'verify': code,
            'machine': base64.b64encode(str(get_random_code(4)).encode('utf-8')).decode('utf-8'),
            'randomNum': self.rcode,
            'agencyid': 4626,
            "mobileagencyid": "undefined",
            'mobileusername': '',
            'ts': int(time.time() * 1000),
        }
        d['sign'] = get_sign(d)
        del d['mobileagencyid']

        res = self.do_post(url, data=d)
        if res.status_code == 200:
            token = get_token_code(res.json())
            return token
        else:
            return False

    def has_chapter_yuwen(self, course_id):
        """获取章节"""
        url = f'/BeegoEduApi/api/pc/getChapterExerciseList/{self.umcid}/{course_id}' if course_id > 700000 else f'/BeegoEduApi/api/pc/gensimexamreListBysrId/{self.umcid}/{course_id}/-2'
        res = self.do_get(url)
        if res.status_code == 200:
            questions = get_quest_listy(res.json(), course_id)
            return questions
        else:
            return False

    def do_get(self, url, params=None):
        if self.token:
            self.headers.update(
                {"Token": self.token})
        return self.get(self.host + url, params=params)

    def do_post(self, url, data=None, json=None):
        self.headers.update(
            {"Token": self.token})
        return self.post(self.host + url, data=data, json=json)


def start():
    x = MyClass()
    # 取token
    token = x.has_token()
    if not token:
        raise Exception('获取token失败')
    x.token = token
    print("默认token:", token)

    # 取验证码
    while True:
        # 取验证码
        code = x.has_code()
        print("验证码2:", code, "\n", "-" * 10)
        if code:
            break
        time.sleep(1)
    print("验证码3:", code)

    # 登录
    login = x.has_login(code)
    if not login:
        raise Exception('登录失败')
    x.token = login
    print("用户token:", login)

    # 检查headers
    # for k, v in x.headers.items():
    #     print(k, v)

    # =====================================================
    # 解析题库
    # quest = x.has_chapter(707000)
    # if not quest:
    #     raise Exception('解析题库失败')
    # print("题库:", quest)
    # with open("quest2.json", "w", encoding="utf-8") as f:
    #     json.dump(quest, f, ensure_ascii=False)
    # =====================================================

    # 加载
    try:
        with open("yuwen.json", "r", encoding="utf-8") as f:
            YUWEN = json.load(f)
    except BaseException as err:
        YUWEN = {"finish": []}

    # 语文
    for i in x.idx["yuwen"]:
        if i in YUWEN["finish"]:
            continue
        print("Ask:", i)
        quest = x.has_chapter_yuwen(i)
        if not quest:
            raise Exception('解析题库失败')
        YUWEN.update(quest)
        YUWEN['finish'].append(i)

        # 保存
        with open("yuwen.json", "w", encoding="utf-8") as f:
            json.dump(YUWEN, f, ensure_ascii=False)

        time.sleep(100)

    print("Bye")


if __name__ == '__main__':
    print("Hello, World!")
    start()
